var xhr = (function () {

  function _doAjax(opt) {
    var o = window.XMLHttpRequest ?
      new XMLHttpRequest() :
      new ActiveXObject('Microsoft.XMLHTTP');

    if (!o) {
      throw new Error('您的浏览器不支持异步发起HTTP请求');
    }

    var opt = opt || {},
      type = (opt.type || 'GET').toUpperCase(),
      async = '' + opt.async === 'false' ? false : true,
      dataType = opt.dataType || 'JSON',
      jsonp = opt.jsonp || 'cb',
      jsonpCallback = opt.jsonpCallback || 'jQuery' + randomNum() + '_' + new Date().getTime();
    url = opt.url,
      data = opt.data || null,
      timeout = opt.timeout || 30000,
      error = opt.error || function () { },
      success = opt.success || function () { },
      complete = opt.complete || function () { },
      t = null;

    if (!url) {
      throw new Error('您没有填写URL');
    }

    if (dataType.toUpperCase() === 'JSONP' && type !== 'GET') {
      throw new Error('如果dataType为JSONP，type请您设置GET或不设置');
    }

    if (dataType.toUpperCase() === 'JSONP') {
      var oScript = document.createElement('script');
      oScript.src = url.indexOf('?') === -1 ?
        url + '?' + jsonp + '=' + jsonpCallback :
        url + '&' + jsonp + '=' + jsonpCallback;
      document.body.appendChild(oScript);
      document.body.removeChild(oScript);
      window[jsonpCallback] = function (data) {
        success(data);
      };
      return;
    }

    o.onreadystatechange = function () {
      if (o.readyState === 4) {
        if ((o.status >= 200 && o.status < 300) || o.status === 304) {
          switch (dataType.toUpperCase()) {
            case 'JSON':
              success(JSON.parse(o.responseText));
              break;
            case 'TEXT':
              success(o.responseText);
              break;
            case 'XML':
              success(o.responseXML);
              break;
            default:
              success(JSON.parse(o.responseText));
          }
        } else {
          error();
        }
        complete();
        clearTimeout(t);
        t = null;
        o = null;
      }
    }

    o.open(type, url, async);
    type === 'POST' && o.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    o.send(type === 'GET' ? null : formatDatas(data));

    t = setTimeout(function () {
      // o.abort();
      clearTimeout(t);
      t = null;
      o = null;
      throw new Error('本次请求已超时，API地址：' + url);
    }, timeout);
  }

  function formatDatas(obj) {
    var str = '';
    for (var key in obj) {
      str += key + '=' + obj[key] + '&';
    }
    return str.replace(/&$/, '');
  }

  function randomNum() {
    var num = '';
    for (var i = 0; i < 20; i++) {
      num += Math.floor(Math.random() * 10);
    }
    return num;
  }

  return {
    ajax: function (opt) {
      _doAjax(opt);
    },

    post: function (url, data, dataType, successCB, errorCB, completeCB) {
      _doAjax({
        type: 'POST',
        url: url,
        data: data,
        dataType: dataType,
        success: csuccessCB,
        error: errorCB,
        complete: completeCB
      });
    },

    get: function (url, dataType, successCB, errorCB, completeCB) {
      _doAjax({
        type: 'GET',
        url: url,
        dataType: dataType,
        success: csuccessCB,
        error: errorCB,
        complete: completeCB
      })
    }
  }
})();

function trimSpace(str) {
  return str.replace(/\s+/gim, '');
}

function $get(target) {
  var _s = target.charAt(0),
    rTarget = target.replace(_s, '');

  switch (_s) {
    case '#':
      return document.getElementById(rTarget);
    // break;
    case '.':
      return document.getElementsByClassName(rTarget);
    // break;
    default:
      return document.getElementsByTagName(target);
  }
}

/**
 * 格式化时间日期
 * JavaScript时间单位带毫秒
 * PHP时间不带毫秒
 * @ts 时间戳 如1548744604
 * @type 日期格式 如日期/时间/日期+时间
 */
function getDateTime(ts, type) {
  // 转为字符串才有length属性
  var len = ts.toString().length;

  //证明是php以秒为单位的格式,需要转为JS单位
  if (len === 10) {
    ts = ts * 1000;
  }

  //获取年月日时分秒
  var dt = new Date(ts),
    y = dt.getFullYear(),
    //注意：month从0开始
    m = addZero(dt.getMonth() + 1),
    d = addZero(dt.getDate()),
    h = addZero(dt.getHours()),
    i = addZero(dt.getMinutes()),
    s = addZero(dt.getSeconds());

  switch (type) {
    case 'date':
      return y + '-' + m + '-' + d;
    // break;
    case 'time':
      return h + ':' + i + ':' + s;
    // break;
    case 'dateTime':
      return y + '-' + m + '-' + d + ' ' + h + ':' + i + ':' + s;
    // break;
    default:
      return y + '-' + m + '-' + d + ' ' + h + ':' + i + ':' + s;
  }

  //把一位数字补齐为两位 格式为 1 -> 01
  function addZero(num) {
    return num < 10 ? ('0' + num) : num;
  }
}

/**
 * 封装 获取target 函数 并兼容IE
 * @param {*} e 事件对象
 * @param {*} mark 标识 判断是tagName 还是 className
 * @返回值 一个对象包含tar和mark
 */
function getTarget(e, mark) {
  var e = e || window.event,
    tar = e.target || e.srcElement;

  mark = mark == 'className' ? tar.className : tar.tagName.toLowerCase();

  return {
    tar: tar,
    mark: mark
  }
}